//
//  PhotoCollection.m
//  Memento 2.0
//
//  Created by Chris Maddocks on 10-06-27.
//  Copyright 2010 Team Memento. All rights reserved.
//
//  10-08-04: Fix warnings.  (C. Maddocks)
//  10-08-02: Add functions for clearing collection, deleting memories, and initiailizing from an existing Memory  (C. Maddocks)
//  10-08-02: Fix SIGABRT error when moving previous on empty collection.  Add function to add pre-existing memory (e.g., from server) to collection.  (C. Maddocks)
//  10-08-01: Sorting capabilities!  (C. Maddocks)
//  10-07-21: Bump version in header to 2.0.  (C. Maddocks)
//  10-07-20: Fix index out of bounds error when attempting moveLast on new collection.  (C. Maddocks)
//  10-07-19: Implement NSCoding protocol for serialization  (C. Maddocks)
//  10-07-18: Changes to support caching of image data (C. Maddocks)
//  10-07-08: Remove unnecessary retain in setCurrentIndex -- using properties.  (C. Maddocks)
//  10-07-07: Change generateMemory: method so that it does not move the cursor to the new memory (was creating KVO notification issues)
//  (C.Maddocks)
//  10-07-06: Track nextMemoryId in PhotoCollection; make initial changes to plist
//  saving/loading. Not fully implemented yet. Fixed bad init method. (C. Maddocks)
//  10-07-05: generateMemory method in PhotoCollection - skeleton only (C. Maddocks)
//  10-07-02: Implemented camera functionality (M. Toth)
//  10-06-30: Wrote photo collection enumerator functions (C. Maddocks) 
//
// For more information on key-value observing, see: http://developer.apple.com/iphone/library/featuredarticles/KeyValueObserving_QuickStart/Introduction/Introduction.html

#import "PhotoCollection.h"
#import "Memory.h"

@implementation PhotoCollection



@synthesize currentMemory, nextMemoryId;

#pragma mark -
#pragma mark Collection enumerator functions

- (void)moveFirst{
	if (memoryData.count > 0) {
		[self setCurrentIndex:0];
	}
}

- (BOOL)movePrev{
	if (memoryData.count == 0) return FALSE;
	
	if (currentIndex > 0) {
		[self setCurrentIndex:currentIndex-1];
		return TRUE;
	} else return FALSE;
	
}

- (BOOL)moveNext{
	if (memoryData.count == 0) return FALSE;
	
	if (currentIndex < (memoryData.count-1)) {  // The last element in the collection has index count-1
		[self setCurrentIndex:currentIndex+1];
		return TRUE;
	} else return FALSE;

}

- (void)moveLast{
	if (memoryData.count > 0) {
		[self setCurrentIndex:memoryData.count-1];
	}
}


- (int)currentIndex {
	return currentIndex;
}

- (void)setCurrentIndex:(int)idx {
	// Grab the memory ID of the first memory in memoryData
	currentIndex = idx;
	self.currentMemory = [memoryData objectAtIndex:idx];  	
}

- (int)count {
	return memoryData.count;
}


#pragma mark -
#pragma mark Adding / editing functions

// Create a new memory with values as specified in the dictionary, and add it to the PhotoCollection.
// For a list of keys that can be used in the dictionary, see Memory class.
- (void)addMemoryWithContentsOfDictionary:(NSDictionary *)aDictionary {
	Memory *memory = [[Memory alloc] initWithDictionary:aDictionary];
	[memoryData addObject:memory];
	[self setCurrentIndex:memoryData.count-1];
	[memory release];
}

// Add an existing memory instance to the PhotoCollection.
- (void)addMemory:(Memory *)memory {
	if (memory != nil) {	
		[memoryData addObject:memory];
		[self setCurrentIndex:memoryData.count-1];
	}
}

// Create a new empty memory with a unique memoryId.
- (Memory *)generateMemoryWithImage:(UIImage *)aImage location:(CLLocationCoordinate2D)aLocation {
	Memory *memory = [[Memory alloc] initWithMemoryId:nextMemoryId++];
	memory.image = aImage;
	memory.location = aLocation;
	[memoryData addObject:memory];
	[self setCurrentIndex:memoryData.count-1];
	return [memory autorelease];	
}

// Delete the current memory, and move to the next memory (or last memory, if we were on the last)
- (void)deleteCurrentMemory {
	[memoryData removeObjectAtIndex:currentIndex];
	if (self.currentIndex < [memoryData count]) {
		self.currentIndex = self.currentIndex;
	} else {
		[self moveLast];
	}
}

- (void)clearCollection {
	currentMemory = nil;
	currentIndex = 0;
	[memoryData removeAllObjects];
}



#pragma mark -
#pragma mark NSCoding methods

// Encodes our memoryData array and nextMemoryId, and passes them to coder for serialization
- (void)encodeWithCoder:(NSCoder *)coder
{
	[coder encodeObject:memoryData forKey:@"memoryData"];
	[coder encodeInt:nextMemoryId forKey:@"nextMemoryId"];
}

// Initializes a PhotoCollection based on contents received via coder (for serialization)
- (id)initWithCoder:(NSCoder *)coder
{
	[super init];
	[memoryData release];
	memoryData = [[coder decodeObjectForKey:@"memoryData"] retain];
	nextMemoryId = [coder decodeIntForKey:@"nextMemoryId"];
	currentIndex = 0;

	if (memoryData == NULL) {
		memoryData = [[NSMutableArray alloc] init];
	}
	
	return self;
}

#pragma mark -
#pragma mark Sorting and other serialization functions

- (void)sortBy:(int)sortMethod{
	NSSortDescriptor *sortDesc = nil;
	
	if (sortMethod == kSortByLocation) {
		sortDesc = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:NO];
	} else {
		sortDesc = [[NSSortDescriptor alloc] initWithKey:@"dateTime" ascending:YES];
	}
	
	[memoryData sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
	currentIndex = [memoryData indexOfObject:currentMemory];  // Since the position of the currently visible memory will have changed
	
	// Make sure the current memory pointer points to a valid memory
	if (currentIndex > [memoryData count]-1) {
		[self moveLast];
	}
	
	[sortDesc release];	
}


// Return full data path to location where memory images and audio should be stored.
// Currently, returns user's sandboxed documents directory.
- (NSString *)collectionDataPath {
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
	NSString *documentsDirectory = [paths objectAtIndex:0];
	
	return documentsDirectory;
}

#pragma mark -
#pragma mark Initialization and cleanup

- (id)init {
	[super init];
	
	nextMemoryId = 1;
	currentIndex = 0;
	memoryData = [[NSMutableArray alloc] init];
	
	return self;
}

- (void)dealloc {
	[memoryData release];
	[super dealloc];
}

@end
